package com.dongdongshop.txmessage;


import com.alibaba.dubbo.config.annotation.Reference;
import com.dongdongshop.pojo.pay.TbPayLog;
import com.dongdongshop.service.PayLogServiceI;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;

import javax.annotation.Resource;

/**
 * mq事物消息监听类
 */
@RocketMQTransactionListener(txProducerGroup = "tx-stockCount")
public class MQTXListener implements RocketMQLocalTransactionListener {
    @Reference
    private PayLogServiceI payLogServiceI;
    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 执行本地事物的方法
     * 当我们本地事物执行成功后会像MQ返回  COMMIT, ROLLBACK, UNKNOWN;
     *
     * @param message :想要发送的消息信息
     * @param arg  ：执行本地事物需要用到的数据 （例如：减库存 商品id ，库存数量等等）
     * @return
     */
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object arg) {
        //一般情况下会讲messageId存到reds中 方法一
        //String messageId = message.getHeaders().getId().toString();
      try {
          //本地事物要用的参数
          TbPayLog payLog=(TbPayLog)arg;
          //要发送的信息
          String msg=new String((byte[]) message.getPayload());
          //修改订单和paylog的状态 保存数据库
          payLogServiceI.updatePayByOutTradeNo(payLog);
          System.out.println("将要发送的消息"+msg);
          System.out.println("本地事务需要的参数"+arg);
          //redisTemplate.boundHashOps("tx-stockCount").put(messageId,"true");
      }catch (Exception e){
          e.printStackTrace();
          //将本地事物执行状态return到MQ服务，并且保存到redis备份（网络延迟，MQ服务产生回调的时候 可以从redis中获取）
          //将消息id保存到redis中
         //redisTemplate.boundHashOps("tx-stockCount").put(messageId,"false");
          //讲messageId存到reds中 或者事物id
          //方法二 事物id  Object transaction_id=message.getHeaders().get("TRANSACTION_ID")
          redisTemplate.opsForValue().set(message.getHeaders().get("TRANSACTION_ID"),"2");
         return RocketMQLocalTransactionState.ROLLBACK;//异常
      }
      //讲messageId存到reds中 或者事物id ， 为了事物的回查
        redisTemplate.opsForValue().set(message.getHeaders().get("TRANSACTION_ID"),"1");
        return RocketMQLocalTransactionState.COMMIT;//成功
    }

    /**
     * 可能会出现网络不稳定的问题 都数据包 本地事物会查方法
     *
     * @param message ：发送的消息 mq会带着我们要发送的消息回查
     * @return
     */
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
        //通过消息的id查询有没有处理过并且是否处理成功，因为mq没有收到 主动过来看一眼

        String status = (String) redisTemplate.opsForValue().get(message.getHeaders().get("TRANSACTION_ID").toString());
        if ("1".equals(status)){
            return RocketMQLocalTransactionState.COMMIT;
        }else if ("2".equals(status)) {
            //继续处理，或者直接回滚
            return RocketMQLocalTransactionState.ROLLBACK;
        } else {
            return RocketMQLocalTransactionState.UNKNOWN;
        }
        /*对应方法一*/
       /* String string = message.getHeaders().getId().toString();
        boolean flag = (boolean) redisTemplate.boundHashOps("tx-stockCount").get(string);
        if (true){
            return RocketMQLocalTransactionState.COMMIT;
        }else {
            return RocketMQLocalTransactionState.ROLLBACK;
        }*/

    }
}
